package org.dce.screencapturer;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.dce.screencapturer.objects.DrawingObject;

public class SelectionHandler 
	implements ContainerListener{

	private final Drawing drawingArea;
	private final ComponentSelectionHandler componentSelectionHandler = new ComponentSelectionHandler();
	private final AreaSelectionHandler areaSelectionHandler = new AreaSelectionHandler();
	private final Set<DrawingObject> selectedComponents = new HashSet<DrawingObject>();
	private List<SelectionListener> listeners = new ArrayList<SelectionListener>();
	
	public SelectionHandler(Drawing drawingArea){
		this.drawingArea = drawingArea;
		this.drawingArea.addContainerListener(this);
		this.drawingArea.addMouseListener(areaSelectionHandler);
	}

	public void addSelectionListener(SelectionListener selectionListener){
		if (!listeners.contains(selectionListener)){
			this.listeners.add(selectionListener);
		}
	}
	
	public void removeSelectionListener(SelectionListener selectionListener){
		this.listeners.remove(selectionListener);
	}
	
	protected void notifySelectionChanged(){
		SelectionEvent event = new SelectionEvent(this);
		for (SelectionListener listener:listeners){
			listener.selectionChanged(event);
		}
	}
	@Override
	public void componentAdded(ContainerEvent e) {
		e.getChild().addMouseListener(componentSelectionHandler);
	}

	@Override
	public void componentRemoved(ContainerEvent e) {
		e.getChild().removeMouseListener(componentSelectionHandler);
	}
	
	private class ComponentSelectionHandler 
		extends MouseAdapter{

		@Override
		public void mousePressed(MouseEvent e) {
			
			DrawingObject component = (DrawingObject)e.getComponent();
			
			int modifiers = e.getModifiers();
			
			if ((modifiers & MouseEvent.CTRL_MASK) != 0){
				if (!selectedComponents.add(component)){
					selectedComponents.remove(component);
				}
			} else {
				selectedComponents.clear();
				selectedComponents.add(component);
			}
			
			notifySelectionChanged();
		}
	}
	
	private class AreaSelectionHandler 
		extends MouseAdapter{
		
		private Point firstPoint;
		
		
		public void mousePressed(MouseEvent event){
			firstPoint = event.getPoint();
		}
		
		public void mouseReleased(MouseEvent event){
			Point secondPoint = event.getPoint();
			
			int x = Math.min(firstPoint.x, secondPoint.x);
			int y = Math.min(firstPoint.y, secondPoint.y);
			int width = Math.max(firstPoint.x, secondPoint.x) - x;
			int height = Math.max(firstPoint.y, secondPoint.y) - y;
			
			Rectangle rectangle = new Rectangle(x,y,width,height);
			
			for (DrawingObject c:drawingArea.getDrawingObjects()){
				if (c.intersects(rectangle)){
					selectedComponents.add(c);
				}
			}
			notifySelectionChanged();
		}
	}
	
	public boolean isSelected(DrawingObject c){
		return selectedComponents.contains(c);
	}

	public Set<DrawingObject> getSelection() {
		return selectedComponents;
	}

}
